// 
// 
// 

#include "DustSensor.h"

//
// 10ms周期的PWM，脉冲宽度为320ms，在280ms - 320ms之间读取采样值
//
static const int delayTime = 280;
static const int delayTime2 = 40;
static const int offTime = 9680;

//
// 最大采样次数设定
//
static const int sampleCntMax = 3;

//
// 传感器初始化函数
// 初始化后建议等待1s以上再读取
// ledPwrPin - 连接到数字脚
// dustPin - 连接到模拟输入脚
//
void DustSensor::Init(int ledPwrPin, int dustPin)
{
	pinMode(ledPwrPin, OUTPUT);
	//
	// 关闭传感器LED
	//
	digitalWrite(ledPwrPin, HIGH);

	this->ledPwrPin = ledPwrPin;
	this->dustPin = dustPin;

	sampleCnt = 0;
	ppm = 0;
}

//
// 环境灰尘采样函数
// 该函数每执行一次，就会进行一次采样
// 该函数建议在主循环中不断执行，以获取更多的采样值来判断
// 环境的灰尘量
// 
// 返回值是采样的值
//
int DustSensor::Sample(void)
{
	//
	// 点亮LED
	//
	digitalWrite(ledPwrPin, LOW);
	delayMicroseconds(delayTime);
	this->dustVal = analogRead(this->dustPin);
	delayMicroseconds(delayTime2);
	//
	// 关闭LED
	//
	digitalWrite(ledPwrPin, HIGH);
	delayMicroseconds(offTime);

	this->sampleCnt++;
	this->ppm += this->dustVal;

	if (sampleCnt > sampleCntMax)
	{
		this->DustDataUpdate();
	}

#ifdef DEBUG_ON
	Serial.print("#sampleCnt = ");
	Serial.println(sampleCnt);
	Serial.print("#ppm = ");
	Serial.println(ppm);
#endif

	return dustVal;
}

//
// 用来更新灰尘的状态数据
// 包括：voltage, dustDensity, ppmPercf (Particles per 0.01 cubic foot)
// 0.01立方英尺颗粒物个数
//
void DustSensor::DustDataUpdate(void)
{
	voltage = (ppm / (sampleCnt)) * (5.0 / 1024);
	// 这里计算出来的是mg/m3，下面的是拟合公式。
	dustDensity = 0.172 * voltage - 0.0999;
	ppmPercf = (voltage - 0.0356) * 120000;

#ifdef DEBUG_ON
	Serial.print("#voltage = ");
	Serial.println(voltage);
	Serial.print("#dustDensity = ");
	Serial.println(dustDensity);
	Serial.print("#ppmPercf = ");
	Serial.println(ppmPercf);
#endif

	if (dustDensity < 0)
	{
		dustDensity = 0;
	}
	if (dustDensity > 0.5)
	{
		dustDensity = 0.5;
	}

	if (ppmPercf < 0)
	{
		ppmPercf = 0;
	}
	
	//
	// 重置，进行下一轮计算
	// 
	sampleCnt = 0;
	ppm = 0;
}
